package com.itheima.server.service;

import com.alibaba.fastjson.JSON;
import com.itheima.commons.template.AipFaceTemplate;
import com.itheima.commons.template.HuanXinTemplate;
import com.itheima.commons.template.OssTemplate;
import com.itheima.commons.template.SmsTemplate;
import com.itheima.domain.db.User;
import com.itheima.domain.db.UserFreeze;
import com.itheima.domain.db.UserInfo;
import com.itheima.domain.vo.ErrorResult;
import com.itheima.dubbo.api.UserApi;
import com.itheima.dubbo.api.UserFreezeApi;
import com.itheima.dubbo.api.UserInfoApi;
import com.itheima.server.client.UserFreezeClient;
import com.itheima.server.interceptor.UserHolder;
import com.itheima.server.util.JwtUtils;
import org.apache.commons.codec.digest.DigestUtils;
import org.apache.commons.lang3.StringUtils;
import org.apache.dubbo.config.annotation.Reference;
import org.apache.rocketmq.spring.core.RocketMQTemplate;
import org.joda.time.DateTime;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.http.ResponseEntity;
import org.springframework.stereotype.Service;
import org.springframework.web.client.RestTemplate;
import org.springframework.web.multipart.MultipartFile;

import java.io.IOException;
import java.time.Duration;
import java.util.HashMap;
import java.util.Map;

/**
 * @author 阿鹏
 * @date 2021/1/23 20:00
 */
@Service
public class UserService {

    @Reference
    private UserApi userApi;

    @Reference
    private UserInfoApi userInfoApi;

    @Value("${tanhua.secret}")
    private String secret;

    @Autowired
    private SmsTemplate smsTemplate;

    @Autowired
    private HuanXinTemplate huanXinTemplate;

    @Autowired
    private OssTemplate ossTemplate;

    @Autowired
    private AipFaceTemplate aipFaceTemplate;
    @Autowired
    private RocketMQTemplate rocketMQTemplate;
    @Autowired
    private UserFreezeClient client;
    @Autowired
    private RedisTemplate<String, String> redisTemplate;


    // 向Redis中存储验证码的前缀
    private String codePrefix = "CODE_";
    // token前缀
    private String tokenPrefix = "TOKEN_";

    /**
     * 修改发送验证码的逻辑
     * 先查询数据库此手机号是否存在
     * 存在: 判断当前用户是否被封禁
     * 1.封禁如果是永久,验证码不给发送,省钱
     * 2.封禁如果是其他,均给发送,冻结登录的在登录那里判断
     * 不存在: 发送验证码
     */
    public ResponseEntity sendVerifyCode(String phone) {

        // 在发送验证码之前先查询当前手机号是否存在
        User user = userApi.findByMobile(phone);
        // 如果用户存在 判断
        if (user != null) {
            String str = redisTemplate.opsForValue().get("USER_PREFIX_" + user.getId());
            if (StringUtils.isNotBlank(str)) {
                UserFreeze freeze = client.findByUserId(user.getId());
                if (freeze.getFreezingTime() == 3) {
                    // 如果是永久冻结,验证码都不给你发
                    return ResponseEntity.status(500).body(ErrorResult.foreverInvalid());
                }
            }
        }

        // 发送验证码
        //String code = smsTemplate.sendSms(phone);
        String code = "123456";
        redisTemplate.opsForValue().set(codePrefix + phone, code, Duration.ofMinutes(5));
        return ResponseEntity.ok(null);
    }

    public ResponseEntity loginVerification(String phone, String code) {

        // 在登录之前先查询当前手机号
        User u = userApi.findByMobile(phone);
        if (u != null) {
            String str = redisTemplate.opsForValue().get("USER_PREFIX_" + u.getId());
            if (StringUtils.isNotBlank(str)) {
                UserFreeze freeze = client.findByUserId(u.getId());
                if (freeze.getFreezingRange() == 1) {
                    // 冻结登录
                    return ResponseEntity.status(500).body(ErrorResult.loginInvalid());
                }
            }
        }

        String value = redisTemplate.opsForValue().get(codePrefix + phone);
        if (value == null || !value.equals(code)) {
            return ResponseEntity.status(500).body(ErrorResult.smsInvalid());
        }
        // 使用完验证码给从redis中删除
        redisTemplate.delete(codePrefix + phone);

        // 手机号登录
        String type = "0101"; // 表示登录
        User user = userApi.findByMobile(phone);
        boolean isNew = false;
        if (user == null) {
            user = new User();
            user.setMobile(phone);
            user.setPassword(DigestUtils.md5Hex("123456"));

            long id = userApi.save(user);
            user.setId(id);
            isNew = true;

            // 将用户注册到环信中
            huanXinTemplate.register(user.getId());
            type = "0102"; // 表示注册
        }

        // 使用rocketMq发送消息
        Map<String, Object> message = new HashMap<>();
        message.put("userId", user.getId());
        message.put("type", type);
        message.put("date", new DateTime().toString("yyyy-MM-dd"));
        rocketMQTemplate.convertAndSend("tanhua-log", message);


        // 生成令牌
        String token = JwtUtils.createToken(phone, user.getId(), secret);
        // 将user对象放在缓存中
        redisTemplate.opsForValue().set(tokenPrefix + token, JSON.toJSONString(user), Duration.ofHours(1));

        // 构造返回值
        Map<String, Object> result = new HashMap<>();
        result.put("token", token);
        result.put("isNew", isNew);
        return ResponseEntity.ok(result);
    }

    public ResponseEntity loginReginfo(UserInfo userInfo) {
        User user = UserHolder.getUser();
        userInfo.setId(user.getId());
        userInfoApi.save(userInfo);
        return ResponseEntity.ok(null);
    }

    public User findUserByToken(String token) {
        String userJson = redisTemplate.opsForValue().get(tokenPrefix + token);
        if (userJson == null) {
            return null;
        }
        User user = JSON.parseObject(userJson, User.class);
        // 客户端每访问一次,就给redis中的user加1小时
        redisTemplate.opsForValue().set(tokenPrefix + token, userJson, Duration.ofHours(1));
        return user;
    }

    public ResponseEntity uploadHead(MultipartFile headPhoto) throws IOException {
        User user = UserHolder.getUser();
        boolean detect = aipFaceTemplate.detect(headPhoto.getBytes());
        if (!detect) {
            return ResponseEntity.status(500).body(ErrorResult.faceDetectFailed());
        }
        String path = ossTemplate.upload(headPhoto.getOriginalFilename(), headPhoto.getInputStream());
        UserInfo userInfo = new UserInfo();
        userInfo.setId(user.getId());
        userInfo.setAvatar(path);
        userInfoApi.update(userInfo);
        return ResponseEntity.ok(null);
    }


    private int convertDay(UserFreeze freeze) {
        int day = 0;
        if (freeze.getFreezingTime() == 1) {
            day = 3;
        } else if (freeze.getFreezingTime() == 2) {
            day = 7;
        }
        return day;
    }
}
